<?php
/**
 * Class Pagination
 * @author nhuantp@fpt.net
 */
class Util_Pagination
{
    public $base_url			= '';	// The page we are linking to
    public $total_rows  		= '';	// Total number of items (database results)
    public $per_page	 		= 20;	// Max number of items you want shown per page
    public $num_links			= 5;	// Number of "digit" links to show before/after the currently viewed page
    public $cur_page	 		= 0;	// The current page being viewed
    public $first_link   		= '';
    public $prev_link			= '&laquo;Previous';
    public $next_link			= 'Next &raquo;';
    public $last_link			= '';
    public $full_tag_open		= '<ul class="pagination">';
    public $full_tag_close		= '</ul>';
    public $first_tag_open		= '';
    public $first_tag_close		= '';
    public $last_tag_open		= '';
    public $last_tag_close		= '';
    public $cur_tag_open		= '<li class="active">';
    public $cur_tag_close		= '</li>';
    public $prev_tag_open		= '<li class="previous-off">';
    public $prev_tag_close		= '</li>';
    public $next_tag_open		= '<li class="next">';
    public $next_tag_close		= '</li>';
    public $num_tag_open		= '<li>';
    public $num_tag_close		= '</li>';
    public $digit_tag_open		= '';
    public $digit_tag_close		= '';

    /**
     * Constructor of class
     */
    public function __construct($params = array())
    {
        if ( count($params) > 0 )
        {
            $this->initialize($params);
        }//end if
    }

    /**
     * Initialize
     */
    public function initialize($params = array())
    {
        if ( count($params) > 0 )
        {
            foreach ( $params as $key=>$val )
            {
                if ( isset($this->$key) )
                {
                    $this->$key	= $val;
                }//end if
            }//end foreach
        }//end if
    }

    /**
     * Create links
     */
    public function create_links()
    {
        // If our item count or per-page total is zero there is no need to continue.
        if ( $this->total_rows == 0 || $this->per_page == 0 )
        {
            return '';
        }//end if

        // Calculate the total number of pages
        $num_pages	= ceil($this->total_rows/$this->per_page);

        // Is there only one page? Hm... nothing more to do here then.
        if ( $num_pages == 1 )
        {
            return '';
        }//end if

        $this->num_links	= (int)$this->num_links;

        if ( $this->num_links < 1 )
        {
            return '';
        }//end if

        if ( !is_numeric($this->cur_page) )
        {
            $this->cur_page	= 0;
        }//end if

        // Is the page number beyond the result range?
        // If so we show the last page
        if ( $this->cur_page > $num_pages )
        {
            $this->cur_page	= $num_pages;
        }//end if

        // Calculate the start and end numbers. These determine
        // which number to start and end the digit links with
        if ( $this->cur_page <= 1 )
        { //is first page
            $start	= 1;
            $end	= $start+($this->num_links-1);
        } elseif ( $this->cur_page >= $num_pages )
        { //is last page
            $end	= $num_pages;
            $start	= $end-($this->num_links-1);
            $start	= $start<1?1:$start;
        } else
        {
            if ( (($this->cur_page-floor($this->num_links/2)) >= 1) && (($this->cur_page+floor($this->num_links/2)) <= $num_pages) )
            {
                $start	= $this->cur_page-floor($this->num_links/2);
                $start	= $start<1?1:$start;
                $end	= $start+($this->num_links-1);
            } elseif ( ($this->cur_page-floor($this->num_links/2)) < 1 )
            {
                $start	= 1;
                $end	= $start+($this->num_links-1);
            } else
            {
                $end	= $num_pages;
                $start	= $end-($this->num_links-1);
            }//end if
        }//end if

        $start	= $start<1?1:$start;
        $end	= $end>$num_pages?$num_pages:$end;

        // And here we go...
        $output	= '';

        // Render the "First" link
        if ( $this->cur_page > 1 && $this->first_link != '' )
        {
            $output	.= $this->first_tag_open.'<a href="'.$this->base_url.'/page/1">'.$this->first_link.'</a>'.$this->first_tag_close;
        }//end if

        // Render the "previous" link
        if ( $this->cur_page > 1 )
        {
            $this->prev_tag_open	= str_replace('class="previous-off"', 'class="previous"', $this->prev_tag_open);
            $i	= $this->cur_page-1;
            $output	.= " ".$this->prev_tag_open.'<a href="'.$this->base_url.'/page/'.$i.'">'.$this->prev_link.'</a>'.$this->prev_tag_close;
        }
        else
        {
            /*$this->prev_tag_open	= str_replace('class="previous"', 'class="previous-off"', $this->prev_tag_open);
			$output	.= " ".$this->prev_tag_open.$this->prev_link.$this->prev_tag_close;*/
        }//end if

        $output	.= $this->digit_tag_open;

        // Write the digit links
        for ( $loop = $start; $loop <= $end; $loop++ )
        {
            if ( $loop > 0 )
            {
                if ( $this->cur_page == $loop )
                {
                    $output	.= " ".$this->cur_tag_open.'<a href="javascript:;">'.$loop.$this->cur_tag_close."</a> "; // Current page
                } else
                {
                    $output	.= " ".$this->num_tag_open.'<a href="'.$this->base_url.'/page/'.$loop.'">'.$loop.'</a>'.$this->num_tag_close." ";
                }//end if
            }//end if
        }//end for

        $output	.= $this->digit_tag_close;

        // Render the "next" link
        if ( $this->cur_page < $num_pages )
        {
            $this->next_tag_open	= str_replace('class="next-off"', 'class="next"', $this->next_tag_open);
            $output	.= " ".$this->next_tag_open.'<a href="'.$this->base_url.'/page/'.($this->cur_page+1).'">'.$this->next_link.'</a>'.$this->next_tag_close;
        } else
        {
            /*$this->next_tag_open	= str_replace('class="next"', 'class="next-off"', $this->next_tag_open);
			$output	.= " ".$this->next_tag_open.$this->next_link.$this->next_tag_close;*/
        }//end if

        // Render the "Last" link
        if ( $this->cur_page < $num_pages && $this->last_link != '' )
        {
            $i	= $num_pages;
            $output	.= " ".$this->last_tag_open.'<a href="'.$this->base_url.'/page/'.$i.'">'.$this->last_link.'</a>'.$this->last_tag_close;
        }//end if

        // Kill double slashes.  Note: Sometimes we can end up with a double slash
        // in the penultimate link so we'll kill all double slashes.
        $output = preg_replace("#([^:])//+#", "\\1/", $output);

        // Add the wrapper HTML if exists
        $output = $this->full_tag_open.$output.$this->full_tag_close;

        //Return
        return $output;
    }

    /**
     * Create links rewrite
     */
    public function createLinkRewrite()
    {
        // If our item count or per-page total is zero there is no need to continue.
        if ( $this->total_rows == 0 || $this->per_page == 0 )
        {
            return '';
        }//end if

        // Calculate the total number of pages
        $num_pages	= ceil($this->total_rows/$this->per_page);

        // Is there only one page? Hm... nothing more to do here then.
        if ( $num_pages == 1 )
        {
            return '';
        }//end if

        $this->num_links	= (int)$this->num_links;

        if ( $this->num_links < 1 )
        {
            return '';
        }//end if

        if ( !is_numeric($this->cur_page) )
        {
            $this->cur_page	= 0;
        }//end if

        // Is the page number beyond the result range?
        // If so we show the last page
        if ( $this->cur_page > $num_pages )
        {
            $this->cur_page	= $num_pages;
        }//end if

        // Calculate the start and end numbers. These determine
        // which number to start and end the digit links with
        if ( $this->cur_page <= 1 )
        { //is first page
            $start	= 1;
            $end	= $start+($this->num_links-1);
        } elseif ( $this->cur_page >= $num_pages )
        { //is last page
            $end	= $num_pages;
            $start	= $end-($this->num_links-1);
            $start	= $start<1?1:$start;
        } else
        {
            if ( (($this->cur_page-floor($this->num_links/2)) >= 1) && (($this->cur_page+floor($this->num_links/2)) <= $num_pages) )
            {
                $start	= $this->cur_page-floor($this->num_links/2);
                $start	= $start<1?1:$start;
                $end	= $start+($this->num_links-1);
            } elseif ( ($this->cur_page-floor($this->num_links/2)) < 1 )
            {
                $start	= 1;
                $end	= $start+($this->num_links-1);
            } else
            {
                $end	= $num_pages;
                $start	= $end-($this->num_links-1);
            }//end if
        }//end if

        $start	= $start<1?1:$start;
        $end	= $end>$num_pages?$num_pages:$end;

        // And here we go...
        $output	= '';

        // Render the "First" link
        if ( $this->cur_page > 1 && $this->first_link != '' )
        {
            $output	.= $this->first_tag_open.'<a href="'.sprintf($this->base_url, 1).'">'.$this->first_link.'</a>'.$this->first_tag_close;
        }//end if

        // Render the "previous" link
        if ( $this->cur_page > 1 )
        {
            $this->prev_tag_open	= str_replace('class="previous-off"', 'class="previous"', $this->prev_tag_open);
            $i	= $this->cur_page-1;
            $output	.= " ".$this->prev_tag_open.'<a href="'.sprintf($this->base_url, $i).'">'.$this->prev_link.'</a>'.$this->prev_tag_close;
        }
        else
        {
            /*$this->prev_tag_open	= str_replace('class="previous"', 'class="previous-off"', $this->prev_tag_open);
			$output	.= " ".$this->prev_tag_open.$this->prev_link.$this->prev_tag_close;*/
        }//end if

        $output	.= $this->digit_tag_open;

        // Write the digit links
        for ( $loop = $start; $loop <= $end; $loop++ )
        {
            if ( $loop > 0 )
            {
                if ( $this->cur_page == $loop )
                {
                    $output	.= " ".$this->cur_tag_open.'<a href="javascript:;">'.$loop.$this->cur_tag_close."</a> "; // Current page
                } else
                {
                    $output	.= " ".$this->num_tag_open.'<a href="'.sprintf($this->base_url, $loop).'">'.$loop.'</a>'.$this->num_tag_close." ";
                }//end if
            }//end if
        }//end for

        $output	.= $this->digit_tag_close;

        // Render the "next" link
        if ( $this->cur_page < $num_pages )
        {
            $this->next_tag_open	= str_replace('class="next-off"', 'class="next"', $this->next_tag_open);
            $output	.= " ".$this->next_tag_open.'<a href="'.sprintf($this->base_url, $this->cur_page+1).'">'.$this->next_link.'</a>'.$this->next_tag_close;
        } else
        {
            /*$this->next_tag_open	= str_replace('class="next"', 'class="next-off"', $this->next_tag_open);
			$output	.= " ".$this->next_tag_open.$this->next_link.$this->next_tag_close;*/
        }//end if

        // Render the "Last" link
        if ( $this->cur_page < $num_pages && $this->last_link != '' )
        {
            $i	= $num_pages;
            $output	.= " ".$this->last_tag_open.'<a href="'.sprintf($this->base_url, $i).'">'.$this->last_link.'</a>'.$this->last_tag_close;
        }//end if

        // Kill double slashes.  Note: Sometimes we can end up with a double slash
        // in the penultimate link so we'll kill all double slashes.
        $output = preg_replace("#([^:])//+#", "\\1/", $output);

        // Add the wrapper HTML if exists
        $output = $this->full_tag_open.$output.$this->full_tag_close;

        //Return
        return $output;
    }
}